/***************************************************
> Copyright (C) 2024 ==LENA== All rights reserved.
> File Name: tcp_server.c
> Author: lena
> Mail:lena_li@126.com
> Created Time: 2024年11月28日 星期四 22时24分51秒
***************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/epoll.h>
#include <pthread.h>
#include "cJSON.h"
#include <mysql/mysql.h>
int isrun = 1;
int server_socket = 0;
MYSQL mysql;

typedef struct Stu
{
	char name[20];
	char pwd[20];
}Stu;
typedef struct ClientType{
	int epfd;
	int fd;
}ClientType;

int insert_data(MYSQL* mysql,Stu stu);
void handle_signal(int signum)
{
	if(signum == SIGINT)
	{
		isrun = 0;
		close(server_socket);
		exit(0);
	}
}

//入库

void parseJson(const char* p)
{
	Stu s;
	cJSON* root = cJSON_Parse(p);

	cJSON* name = cJSON_GetObjectItem(root,"name");
	cJSON* passwd = cJSON_GetObjectItem(root,"pwd");

	strcpy(s.name, cJSON_GetStringValue(name));
	strcpy(s.pwd ,cJSON_GetStringValue(passwd));

	printf("na:%s,pwd:%s\n",s.name,s.pwd);
	insert_data(&mysql,s);
}

void* read_msg(void* arg)
{
	ClientType ct = *(ClientType*)arg;
	char buf[1024]={0};
	struct epoll_event ev;
	ev.events = EPOLLIN | EPOLLET;
	ev.data.fd = ct.fd;
	while(1)
	{
		memset(buf,0,sizeof(buf));
		int size = read(ct.fd,buf,1023);		

		if(size == -1)
		{
			break;
		}
		//断开连接
		if(size == 0)
		{
			epoll_ctl(ct.epfd,EPOLL_CTL_DEL,ct.fd,&ev);
			close(ct.fd);
		}
		if(size > 0)
		{
			printf("buf:%s\n",buf);	
			//解包
			parseJson(buf);
		}
	}

}

int insert_data(MYSQL* mysql,Stu stu)
{
    char buf[128]= {0};
	printf("name%s,pwd:%s\n",stu.name,stu.pwd);
    sprintf(buf,"insert into tb_user (username,passwd) values ('%s','%s');",stu.name,stu.pwd);
	printf("sqlbuf:%s\n",buf);
    int ret = mysql_multi_query(mysql,buf);
    if( ret != 0)
    {
        printf("insert tb_user fail:%s",mysql_error(mysql));
        return -1;
    }
    return 0;
}

int db_init(MYSQL* mysql)
{
	//初始化mysql句柄
	mysql = mysql_init(NULL);
	if(mysql == NULL)
	{
		printf("init failed");
		return -1;
	}
	//printf("%p",mysql);

	//MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
	//连接数据库
	MYSQL* conn = mysql_real_connect(mysql,"localhost","root","123456","class17",0,NULL,0);
	if(conn == NULL)
	{
		perror("connect failed:");
		return -1;
	}
	return 0;
}
int main(int argc,const char* argv[])
{
	db_init(&mysql);  //数据连接成功的判断
	signal(SIGINT,handle_signal);
	//创建套接字,监听套接字
	server_socket = socket(AF_INET,SOCK_STREAM,0);

	if(argc != 3)
	{
		printf("cmd ip port\n");	
		return -1;
	}
	//bind 本机ip port
	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(atoi(argv[2]));   //port 
	saddr.sin_addr.s_addr = inet_addr(argv[1]);   //port

	int optval = 1;
	//bind 的地址允许重复使用
	setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
	int isbind = bind(server_socket,(struct sockaddr*)&saddr,sizeof(saddr));
	if(isbind == -1)
	{
		perror("bind");
		return -1;
	}

	//启动监听
	int islisten = listen(server_socket,10);
	if(islisten == -1)
	{
		perror("listen");
		return -1;
	}
	printf("监听已启动\n");

	int epfd = epoll_create(1);
	struct epoll_event ev;
	ev.events = EPOLLIN ;
	ev.data.fd = server_socket;

	int ret = epoll_ctl(epfd,EPOLL_CTL_ADD,server_socket,&ev);
	if(ret == -1)
	{
		perror("epoll_ctl")	;
		return -1;
	}
	struct sockaddr_in caddr;
	int addrlen = sizeof(caddr);
	char buf[6] = {0};
	struct epoll_event events[40];
	while(1)
	{
//f:
		int num = epoll_wait(epfd,events,40,5000);
//		if(num == 0)
		{
			printf("num :%d\n",num);
//			goto f;	
		}
#if 1
		for(int i=0;i<num;i++)
		{
			int fd = events[i].data.fd;
			if(fd == server_socket)
			{
				int client_socket = accept(server_socket,(struct sockaddr*)&caddr,&addrlen);
				printf("ip:%s,port:%d\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
				ev.events = EPOLLIN | EPOLLET;
				ev.data.fd = client_socket;
				epoll_ctl(epfd,EPOLL_CTL_ADD,client_socket,&ev);
			}
			int flag = fcntl(fd,F_GETFL);
			flag |= O_NONBLOCK;
			fcntl(fd,F_SETFL,flag);
			//创建子线程,读取数据
			ClientType ct;
			ct.epfd = epfd;
			ct.fd = fd;
			pthread_t tid;
			pthread_create(&tid,NULL,read_msg,(void*)&ct);
			pthread_detach(tid);
		}
#endif
	}
	close(server_socket);

    return 0;
}
